package com.bright.ghj.overt.manager.impl;

import com.bright.ghj.common.pojo.dto.PageDTO;
import com.bright.ghj.common.util.PageUtil;
import com.bright.ghj.common.util.StringUtil;
import com.bright.ghj.overt.converter.DistConverter;
import com.bright.ghj.overt.converter.ZtConverter;
import com.bright.ghj.overt.manager.DistZtManager;
import com.bright.ghj.overt.pojo.dto.DistDTO;
import com.bright.ghj.overt.pojo.dto.ZtAdaptDTO;
import com.bright.ghj.overt.pojo.dto.ZtDTO;
import com.bright.ghj.overt.pojo.po.primary.Dist;
import com.bright.ghj.overt.pojo.po.primary.Zt;
import com.bright.ghj.overt.pojo.query.DistQuery;
import com.bright.ghj.overt.repository.primary.DistRepository;
import com.bright.ghj.overt.repository.primary.ZtRepository;
import com.bright.ghj.overt.util.EntityManagerUtil;
import com.bright.ghj.common.util.ListUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.*;

/**
 * @Author hxj
 * @Date 2024/1/17 14:25
 * @Description
 */
@Component
@RequiredArgsConstructor
public class DistZtManagerImpl implements DistZtManager {

    private final DistRepository distRepository;
    private final ZtRepository ztRepository;

    @PersistenceContext
    private final EntityManager entityManager;

    private final DistConverter distConverter;
    private final ZtConverter ztConverter;

    @Override
    @Cacheable(value = "DistByDistNo", key = "#root.methodName + '_' + #distNo")
    public DistDTO getDistByDistNoByCache(String distNo) {
        List<Dist> dist = distRepository.findAllByDistNo(distNo);
        if (dist.size() > 0) {
            return distConverter.poConvertDTO(dist.get(0));
        }
        return null;
    }

    @Override
    public DistDTO getDistByDistNameByCache(String distName) {
        List<Dist> dist = distRepository.findAllByDistName(distName);
        if (dist.size() > 0) {
            return distConverter.poConvertDTO(dist.get(0));
        }
        return null;
    }

    @Override
//    @Cacheable(value = "ZtByZtId", key = "#root.methodName + '_' + #ztId")
    public ZtDTO getZtByZtIdByCache(String ztId) {
        Zt zt = ztRepository.getByZtId(ztId);
        return ztConverter.poConvertDTO(zt);
    }

    @Override
    public List<DistDTO> listDistByDistNoAndLength(String distNo, int distNoLength, List<String> userDistNo) {
//        String userDistNoStr = userDistNo.size() > 0 ? userDistNo.get(0) : "";
//        List<Dist> dists = distRepository.findAllByDistNoAndLength(distNo, distNoLength, userDistNoStr);
        List<Dist> dists = distRepository.findAllByDistNoAndLength(distNo, distNoLength);
        List<Dist> distsByUserDistNo;
        // 筛选用户有权限看到的地区
        if (userDistNo != null && userDistNo.size() > 0) {
            distsByUserDistNo = ListUtil.toListByFilter(dists, dist -> {
                for (String userDist : userDistNo) {
                    if (StringUtil.startsWith(dist.getDistNo(), userDist)) {
                        return true;
                    }
                }
                return false;
            });
        } else {
            distsByUserDistNo = dists;
        }
        return distConverter.poConvertDTO(distsByUserDistNo);
    }

    @Override
    public List<ZtDTO> listZtByDistNo(DistQuery distQuery) {
        String distNo = distQuery.getDistNo();
        List<String> userDistNo = distQuery.getUserDistNo();
        List<String> userZtId = distQuery.getUserZtId();

        // 筛选用户有权限看到的地区
        boolean isDistNoPermitted = false;
        if (userDistNo != null && userDistNo.size() > 0) {
            for (String userDist : userDistNo) {
                if (StringUtil.startsWith(distNo, userDist)) {
                    isDistNoPermitted = true;
                }
            }
        }
        if (isDistNoPermitted) {
            List<Zt> zts = ztRepository.findAllByDistNoOrderByZtId(distNo);
            // 筛选用户有权限看到的单位
            List<Zt> ztsByUserZtId;
            if (userZtId != null && userZtId.size() > 0) {
                ztsByUserZtId = ListUtil.toListByFilter(zts, zt -> {
                    for (String userZt : userZtId) {
                        if (StringUtil.startsWith(zt.getZtId(), userZt)) {
                            return true;
                        }
                    }
                    return false;
                });
            } else {
                ztsByUserZtId = zts;
            }
            return ztConverter.poConvertDTO(ztsByUserZtId);
        } else {
            return new ArrayList<>();
        }
    }

    @Override
    public PageDTO<ZtDTO> pageZtByDistNo(DistQuery distQuery) {
        // TODO 根据用户所属地区号和账套号限制返回结果 要加到查询语句中
        Pageable pageable = PageUtil.toPageable(distQuery.getPageNumber() - 1, distQuery.getPageSize(), new ArrayList<>());
        Page<Zt> zts = ztRepository.findAllByDistNoOrderByZtId(distQuery.getDistNo(), pageable);
        return PageDTO.of(zts.getTotalElements(), zts.getTotalPages(), ztConverter.poConvertDTO(zts.getContent()));
    }

    @Override
    @Cacheable(value = "ZtFieldValueByZtId", key = "#root.methodName + '_' + #ztId + '_' + #fieldNames.toString()")
    public Map<String, Object> getZtFieldValueByFieldNames(String ztId, List<String> fieldNames) {
        String querySQL = "select " + StringUtil.join(fieldNames.toArray(), ",") + " from zt where ztId=:ztId";
        Map<String, Object> params = new HashMap<>();
        params.put("ztId", ztId);
        List<Map<String, Object>> maps = EntityManagerUtil.queryForMapList(entityManager, querySQL, params);
        if (maps.size() == 0) {
            return new HashMap<>();
        }
        return maps.get(0);
    }

    /**
     * 获取账套信息列表
     *
     * @param ztIds 账套id列表
     * @return 账套列表
     */
    @Override
    public List<ZtDTO> findByZtIds(List<String> ztIds) {
        List<Zt> ztList = ztRepository.findByZtIds(ztIds);
        return ztConverter.poConvertDTO(ztList);
    }

    @Override
    public int getNextLength(String distNo) {
        int distNoLength;
        if (distNo.length() == 2) {
            distNoLength = 4;
        } else if (distNo.length() == 4) {
            distNoLength = 6;
        } else if (distNo.length() == 6) {
            distNoLength = 9;
        } else {
            distNoLength = 12;
        }
        return distNoLength;
    }

    @Transactional
    @Override
    public void saveZtAdapt(ZtAdaptDTO ztDTO) {
//        jdbcTemplatePrimary.update("update zt set zth_import=?, ztName_import=? where ztId=? and id=?",
//                ztDTO.getZthImport(), ztDTO.getZtNameImport(), ztDTO.getZtId(), ztDTO.getId());
        Map<String, Object> params = new HashMap<>();
        params.put("zth_import", ztDTO.getZthImport());
        params.put("ztName_import", ztDTO.getZtNameImport());
        params.put("ztId", ztDTO.getZtId());
        params.put("id", ztDTO.getId());

        EntityManagerUtil.update(entityManager, "update zt set zth_import=:zth_import, ztName_import=:ztName_import where ztId=:ztId and id=:id", params);
    }

    @Override
    public void insertNewDist(DistDTO distDTO) {
        // 确保是新增，不允许随意修改已有的地区信息
        distDTO.setId(null);
        Dist dist = distConverter.dtoConvertPO(distDTO);
        distRepository.save(dist);
    }

    @Transactional
    @Override
    public void updateZtParamsByZtId(String ztId, Map<String, Object> params) {
        if (params.size() == 0) return;

        StringBuilder updateSQL = new StringBuilder("update zt set ");
        List<String> sqlList = new ArrayList<>(params.size());
        // 只保存非空的值
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value != null && StringUtil.isNotEmpty(value.toString())) {
                sqlList.add(key + "=:" + key);
            }
        }
        updateSQL.append(StringUtil.join(sqlList, ",")).append(" where ztId=:ztId");

        params.put("ztId", ztId);
        EntityManagerUtil.update(entityManager, updateSQL.toString(), params);
    }

    @Override
    @Cacheable(value = "ztByZthImport", key = "#root.methodName + '_' + #zthImport")
    public ZtDTO findByZthImportByCache(String zthImport) {
        List<Zt> zts = ztRepository.findAllByZthImport(zthImport);
        if (zts.size() > 0) {
            return ztConverter.poConvertDTO(zts.get(0));
        }
        return null;
    }

}
